<?php
namespace app\common\model;
use think\facade\Cache;
use think\facade\Route;
use think\Image;
use WordAnalysis\Analysis;
use think\Model;
class Article extends TimeModel
{
    protected $type = [
        'publish_time'=>'timestamp',
        'finish_time'=>'timestamp'
    ];
    static function onAfterInsert(Model $model)
    {
        //重新生成网站地图

        self::clearCache();
    }

    static function onAfterUpdate(Model $model)
    {
        $cacheName = 'article_' . $model->id;
        if (Cache::has($cacheName)) {
            Cache::delete($cacheName);
        }
        self::clearCache();
    }

    static function onAfterDelete(Model $model)
    {
        $cacheName = 'article_' . $model->id;
        if (Cache::has($cacheName)) {
            Cache::delete($cacheName);
        }
        self::clearCache();
    }

    public function getTitleAttr($value)
    {
        return html_entity_decode($value);
    }

    public function getContentAttr($value)
    {
        return html_entity_decode($value);
    }

    public function setDescriptionAttr($value)
    {
        return self::clearStrTags($value);
    }

    public function getPublishTimeAttr($value)
    {
        if ($value) {
            return date('Y-m-d H:i:s', $value);
        } else {
            return '';
        }
    }

    static function clearCache()
    {

        if (Cache::has('carouselArticle')) {
            Cache::delete('carouselArticle');
        }
        if (Cache::has('newArticle')) {
            Cache::delete('newArticle');
        }
        if (Cache::has('homeCategory_1')) {
            Cache::delete('homeCategory_1');
        }
        if (Cache::has('homeCategory_2')) {
            Cache::delete('homeCategory_2');
        }
        if (Cache::has('homeCategory_3')) {
            Cache::delete('homeCategory_3');
        }
        if (Cache::has('todayPublishCount')) {
            Cache::delete('todayPublishCount');
        }
    }

    static function todayPublishCount()
    {
        $cacheName = 'todayPublishCount';
        if (Cache::has($cacheName)) {
            $count = Cache::get($cacheName);
        } else {
            $count = (new static())
                ->where('status', 1)
                ->where('publish_time', '>', todayTime())
                ->count();
            Cache::set($cacheName, $count);
        }
        return $count;
    }

    static function categoryUrl($id, $categoryList = [])
    {
        $listMode = sysconfig('article.list_url_mode');
        $listPrefix = sysconfig('article.list_url_prefix');
        $alias = '';
        if (isset($categoryList[$id])) {
            $alias = $categoryList[$id];
        }
        if ($listMode == 4 && $listPrefix && $alias) {
            return '/' . $listPrefix . $alias . '.html';
        } elseif ($listMode == 3 && $listPrefix) {
            return '/' . $listPrefix . $id . '.html';
        } elseif ($listMode == 2 && $alias) {
            return '/' . $alias . '.html';
        } elseif ($listMode == 1 && $alias) {
            return '/list/' . $alias . '.html';
        } else {
            return '/list/' . $id . '.html';
        }
    }

    static function detailUrl($id, $cateId = 0, $categoryList = [])
    {
        $detailMode = sysconfig('article.detail_url_mode');
        $detailPrefix = sysconfig('article.detail_url_prefix');
        $alias = '';
        if (isset($categoryList[$cateId])) {
            $alias = $categoryList[$cateId];
        }
        if ($detailMode == 3 && $detailPrefix) {
            return '/' . $detailPrefix . $id . '.html';
        } elseif ($detailMode == 2) {
            return '/' . $id . '.html';
        } elseif ($detailMode == 1 && $alias) {
            return '/' . $alias . '/' . $id . '.html';
        } else {
            return '/html/' . $id . '.html';
        }
    }

    static function homeCategory($id = 1)
    {
        $categorys = getJsonData('ArticleCategory', 'list');
        $cacheName = 'homeCategory_' . $id;
        if (Cache::has($cacheName)) {
            $list = Cache::get($cacheName);
        } else {
            $articleConf = sysconfig('article');
            $num = $articleConf['homepage_plate_perpage' . $id];
            $_categorys = getJsonData('ArticleCategory', 'list');
            $categorys = array_column($_categorys, 'title', 'id');
            $categoryIds = explode(',', $articleConf['homepage_plate_cates' . $id]);
            $cate = array_column($_categorys, 'alias', 'id');
            $items = [];
            foreach ($categoryIds as $v) {
                if (isset($categorys[$v])) {
                    $_list = (new Article())
                        ->where('category_id', 'in',$v . ls_child_id($_categorys, $v))
                        ->where('is_ad', 0)
                        ->where('out_link', '')
                        ->where('status', 1)
                        ->order('sort', 'desc')
                        ->order('publish_time', 'desc')
                        ->field('id,title,category_id,cover_img,out_link,publish_time')
                        ->limit($num)->select()->toArray();
                    foreach ($_list as &$vv) {
                        $vv['url'] = self::detailUrl($vv['id'], $vv['category_id'], $cate);
                    }
                    $items[] = [
                        'id' => $v,
                        'category' => isset($categorys[$v]) ? $categorys[$v] : '未分类',
                        'list' => $_list
                    ];
                }
            }
            $list = ['name' => $articleConf['homepage_plate_name' . $id], 'list' => $items];
            Cache::set($cacheName, $list);
        }
        return $list;
    }

    static function newArticle()
    {
        if (Cache::has('newArticle')) {
            $list = Cache::get('newArticle');
        } else {
            $articleConf = sysconfig('article');
            $num = $articleConf['newarticle_perpage'];
            $page = $articleConf['newarticle_page'];
            $not_showed_in_news = $articleConf['not_showed_in_news'];
            $categorys = getJsonData('ArticleCategory', 'list');
            $cate = array_column($categorys, 'alias', 'id');
            $cateIds=array_keys($cate);
            $disabledCateIds=(new ArticleCategory())->where('status',0)->column('id');
            $where=[];
            if ($disabledCateIds||$not_showed_in_news) {
                $where[]=['category_id','not in',array_merge($disabledCateIds,explode(',',$not_showed_in_news))];
            }
            $limit = ($num ? $num : 20) * ($page ? $page : 4);
            $list = (new Article())
                ->where($where)
                ->where('status', 1)
                ->order('is_ad', 'desc')
                ->order('sort', 'desc')
                ->order('publish_time', 'desc')
                ->field('id,is_ad,category_id,title,is_bold,keywords,description,title_color,is_top,is_essence,cover_img,out_link,publish_time')
                ->limit($limit)->select()->toArray();
            if(!empty($list)) {
                $cateNames = array_column($categorys, 'title', 'id');
                foreach ($list as &$v) {
                    $cateId=$v['category_id'];
                    $v['url'] = self::detailUrl($v['id'], $cateId, $cate);
                    $v['category'] = isset($cateNames[$cateId])?$cateNames[$cateId]:'未分类';
                }
            }
            $list = array_chunk($list, $num ? $num : 20, false);
            Cache::set('newArticle', $list);
        }
        return $list;
    }

    static function carouselArticle()
    {
        if (Cache::has('carouselArticle')) {
            $data = Cache::get('carouselArticle');
        } else {
            $num = sysconfig('article.carousel_num');

            $data = static::where('is_carousel', 1)
                ->order('publish_time','desc')
                ->limit($num ? $num : 5)
                ->column('id,title,category_id,cover_img,out_link,user_id,description,publish_time');
            if(!empty($data)) {
                $categorys = getJsonData('ArticleCategory', 'list');
                $cate = array_column($categorys, 'alias', 'id');
                foreach ($data as $k=> &$v) {
                    $v['url'] = self::detailUrl($v['id'], $v['category_id'], $cate);
                    if(isset($list[$v['id']])) {
                        $v = array_merge($v, $list[$v['id']]);
                    }
                }
            }
            Cache::set('carouselArticle', $data);
        }
        return $data;
    }


    public function thumb($srcUrl)
    {
        if(strpos($srcUrl,'http')===false) {
            //如果是远程图片先下载
            $filePath = ROOT_PATH . ('/public' . $srcUrl);
            if (!is_file($filePath)) {
                return $srcUrl;
            }
        }else{

            //下载远程图片

            $filePath=$srcUrl;
        }
        if (in_array(self::getExt($srcUrl), ['gif', 'GIF'])) {
            return $srcUrl;
        }
        try {
            $size = getimagesize($filePath);
        }catch (\Exception $e){
            dd($e->getMessage());
        }
        $maxwidth = sysconfig('article.cover_thumb_max');
        if (!$maxwidth) {
            return $srcUrl;
        }
        if ($size[0] > $maxwidth || $size[1] > $maxwidth) {
            $saveName = $filePath . '_thumb.png';
            $image = Image::open($filePath);
            $image->thumb($maxwidth, $maxwidth, 1)->save($saveName);
            return $srcUrl . '_thumb.png';
        }
        return $srcUrl;
    }

    static function getExt($path)
    {
        $path = pathinfo($path);
        if (isset($path['extension'])) {
            return strtolower($path['extension']);
        }
        return '';
    }

    static function curl_get($url, $gzip=false){
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ($curl, CURLOPT_URL, $url);
        curl_setopt ($curl, CURLOPT_REFERER, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
        if($gzip) curl_setopt($curl, CURLOPT_ENCODING, "gzip"); // 关键在这里
        $content = curl_exec($curl);
        curl_close($curl);
        return $content;
    }

    static function downloadImg($src)
    {
//        if(!uri_valid($src)){
//            return $src;
//        }
        $imgUrl = DS . 'uploads' . DS . 'article_img' . DS;
        $arr=explode('.',basename($src));
        $ext =$arr[1];

        $filename = md5(microtime()) . '.' . $ext;
        $savePath = ROOT_PATH . 'public' . $imgUrl . $filename;
        $path = str_replace("\\", "/", $imgUrl . $filename);
        $realpath = WEB_ROOT . $path;

        $dir = dirname($savePath);
        if (!is_dir($dir)) {
            mkdir($dir, 0777, true);
        }
        $context = stream_context_create(
            array(
                "http" => array(
                    "header" => "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
                )
            )
        );
        $stream = file_get_contents("compress.zlib://" . $src,FALSE,$context);

        file_put_contents($savePath, $stream);
        if (is_file($savePath)) {
            return $realpath;
        } else {
            return $src;
        }
    }

    public static function clearStrTags($content)
    {
        $content = html_entity_decode($content);
        //将空格替换成空
        $content = str_replace(" ", "", $content);
        //函数剥去字符串中的 HTML、XML 以及 PHP 的标签,获取纯文本内容
        $content = strip_tags($content);
        //去除转义字符
        return str_replace(array("&nbsp;", "&ensp;", "&emsp;", "&thinsp;", "&zwnj;", "&zwj;", "&ldquo;", "&rdquo;"), "", $content);
    }
    function filterEmoji($str) {
        $str = preg_replace_callback(
            '/./u',
            function (array $match) {
                return strlen($match[0]) >= 4 ? '' : $match[0];
            },
            $str);
        return $str;
    }
    public function createNew($data)
    {
        $this->filterFields($data, $articleData, $attributeData, $attach);
        if (isset($articleData['cover_img']) && $articleData['cover_img']) {
            $cover_img = $articleData['cover_img'];
            if (strpos($cover_img, 'http') !== false) {
                $cover_img = self::downloadImg($cover_img);
            }
            $articleData['cover_img'] = $this->thumb($cover_img);
        }
        $article = $this->create($articleData);
        $articleId = $article->id;
        $attributeData['article_id'] = $articleId;
        $attributeData['content']=$this->filterEmoji($attributeData['content']);
        try {
            (new ArticleAttribute())->create($attributeData);
        }catch (\Exception $e){
            dd($attributeData);
        }
        if (isset($attach['attachlink']) && !empty($attach['attachlink']) && isset($attach['attachlink']['urls'])) {
            hooks('attachlink.link_save', array_merge($attach['attachlink'], ['subject_id' => $articleId, 'subject' => 'ARTICLE']));
        }
        return $article;
    }

    public function category()
    {
        return $this->belongsTo('ArticleCategory', 'category_id', 'id');
    }

    public function attribute()
    {
        return $this->hasOne('ArticleAttribute', 'article_id', 'id');
    }

    public static function getCDK($content,$title,$backType = 'CDK')
    {
        $data = [
            'C' => '',
            'D' => '',
            'K' => ''
        ];
        if ($content == '') {
            return $data;
        }
        //获取封面、描述、关键字
        $arr = str_split($backType);
        $data = [];
        if (in_array('C', $arr)) {
            $data['C'] = get_coverpic($content);
        }
        if (in_array('D', $arr)) {
            $data['D'] = get_description($content);
        }
        if (in_array('K', $arr)) {
            $data['K'] = Analysis::getKeywords($title);
        }
        return $data;
    }

    public static function getDetail($id)
    {
        $cacheName = 'article_' . $id;
        if (Cache::has($cacheName)) {
            $data = Cache::get($cacheName);
        } else {
            $data = (new static())
                ->where('id', $id)
                ->find();
            if($data){
                $data=$data->toArray();
                $attrs=(new ArticleAttribute())->where('article_id',$data['id'])->find()->toArray();
                $data=array_merge($attrs,$data);
                $category=ArticleCategory::getItemById($data['category_id'],'title');
                $data['category']=$category?:'未分类';
            }
            Cache::set($cacheName, $data);
        }
        return $data;
    }

    public function getJsonData($name, $param = [])
    {
        $page = 1;
        $limit = 20;
        if (isset($param['page'])) {
            $page = $param['page'];
        }
        if (isset($param['limit'])) {
            $limit = $param['limit'];
        }
        switch ($name) {
            case 'last_updated':
                $list = $this->alias('a')
                    ->join('article_category b', 'a.category_id=b.id')
                    ->where('b.status', 1)
                    ->where('a.status', 1)
                    ->where('last_updated_show', 1)
                    ->order('is_ad', 'desc')
                    ->order('a.sort', 'desc')
                    ->order('publish_time', 'desc')
                    ->field('a.id,title,is_ad,is_essence,publish_time')
                    ->page($page, $limit)
                    ->select();
                break;
        }
        return [
            'code' => 1,
            'data' => $list
        ];
    }


    public static function checkAuth($userId)
    {
        $config = sysconfig('article');
        $where['user_id'] = $userId;
        $model = (new static());
        $todatTime = strtotime(date("Y-m-d"));
        if (@$config['post_interval']) {
            $interval = $config['post_interval'];
            $lastSend = $model
                ->where($where)
                ->order('id', 'desc')
                ->limit(1)
                ->value('create_time');

            if ($lastSend && (@$lastSend + 60 * $interval) > time()) {
                return array('code' => -1, 'msg' => '频率过快，请稍后再试');
            }
        }

        if (@$config['user_day_max']) {
            $mobileMax = $config['user_day_max'];
            $mobileCount = $model
                ->where('create_time', '>', $todatTime)
                ->where($where)
                ->count();
            if ($mobileCount >= $mobileMax) {
                return array('code' => -1, 'msg' => '每个用户每天限制投稿' . $mobileMax . '篇');
            }
        }

        if (@$config['ip_day_max']) {
            $ipMax = $config['ip_day_max'];
            $ipCount = $model
                ->where('create_time', '>', $todatTime)
                ->where('user_ip', request()->ip())
                ->count();
            if ($ipCount >= $ipMax) {
                return array('code' => -1, 'msg' => '每个IP每天限制投稿' . $ipMax . '篇');
            }
        }
        return true;
    }

    public function filterFields($data, &$mainData, &$attributeData, &$otherData)
    {
        $mainField = $this->getTableFields();
        $attributeField = (new ArticleAttribute())->getTableFields();
        foreach ($data as $key => $value) {
            if (in_array($key, $mainField)) {
                $mainData[$key] = trim($value);
            } elseif (in_array($key, $attributeField)) {
                $attributeData[$key] = trim($value);
            } else {
                $otherData[$key] = $value;
            }
        }
    }

    public static function now_here($id, $jiange = '', $ext = '')
    {
        $seoHomeName=sysconfig('seo.home_name');
        $here = '<a href="/">'.($seoHomeName?$seoHomeName:'首页').'</a>';
        $here .= self::get_up_levels($id);
        if ($ext != '') $here .= ' -> ' . $ext;
        if ($jiange) {
            $here = str_replace('->', $jiange, $here);
        }
        return $here;
    }

    protected static function get_up_levels($id)
    {
        $here = '';
        $uplevels = ArticleCategory::field("id,title,pid")->find($id);
        if (!$uplevels) {
            $here .= ' -> <a href="/list/0.html">未分类</a>';
        } else {
            $categorys = getJsonData('ArticleCategory', 'list');
            $cate = array_column($categorys, 'alias', 'id');
            $url = self::categoryUrl($id, $cate);
            $here .= ' -> <a href="' . $url . '">' . $uplevels['title'] . "</a>";
            if ($uplevels['pid'] != 0) {
                $here = self::get_up_levels($uplevels['pid']) . $here;
            }
            return $here;
        }
    }


    public static function createSitemap(){

        $site_url = domain_url('');
        $str = '<?xml version="1.0" encoding="utf-8"?>'.PHP_EOL;
        $str .= '<urlset>'.PHP_EOL;
        $artNum=sysconfig('seo.article_sitemap_num');
        $articles = (New Article())->where('status',1)->order('id','desc')->limit($artNum?$artNum:100)->column('id,category_id,update_time');
        $i=0;
        $categorys = getJsonData('ArticleCategory', 'list');
        $cate = array_column($categorys, 'alias', 'id');
        foreach ($articles as $k => $v) {
            $url=Article::detailUrl($v['id'], $v['category_id'], $cate);
            $priority=($i<=10?'1.0':($i<=50?'0.8':'0.7'));
            $str .= '<url>';
            $str .= '<loc>'.$site_url.$url.'</loc>'.PHP_EOL;
            $str .= '<lastmod>'.date('Y-m-d H:i:s',$v['update_time']).'</lastmod>'.PHP_EOL;
            $str .= '<priority>'.$priority.'</priority >'.PHP_EOL;
            $str .= '<changefreq>daily</changefreq>'.PHP_EOL.PHP_EOL.PHP_EOL;
            $str .= '</url>';
            $i++;
        }

        $articles = (New ArticleCategory())->where('status',1)->order('sort','desc')
            ->order('id','asc')->column('id,alias,update_time');
        $i=0;
        foreach ($articles as $k => $v) {
            $url=Article::categoryUrl($v['id'], $cate);
            $priority=($i<=10?'1.0':($i<=50?'0.8':'0.7'));
            $str .= '<url>';
            $str .= '<loc>'.$site_url.$url.'</loc>'.PHP_EOL;
            $str .= '<lastmod>'.date('Y-m-d H:i:s',$v['update_time']).'</lastmod>'.PHP_EOL;
            $str .= '<priority>'.$priority.'</priority >'.PHP_EOL;
            $str .= '<changefreq>daily</changefreq>'.PHP_EOL.PHP_EOL.PHP_EOL;
            $str .= '</url>';
            $i++;
        }
        $str .='</urlset>'.PHP_EOL;
        file_put_contents(ROOT_PATH."public/sitemap.xml", $str);

    }

}